//------------------------------------------------------------------------------
//  <copyright file="GamePadEmulatorModel.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//  </copyright>
//------------------------------------------------------------------------------

namespace Microsoft.Robotics.Interaction.Visualization
{
    using System;
    using System.Windows;
    using System.Windows.Media.Imaging;
    using Microsoft.Robotics.Interaction.Runtime.Input;
    using Microsoft.Robotics.Visualization;    

    /// <summary>
    /// model that visualizes a game pad emulator
    /// </summary>
    public sealed class GamePadEmulatorModel : Model
    {
        /// <summary>
        /// Default joystick left
        /// </summary>
        private const int DefaultJoystickVisualLeft = 174;

        /// <summary>
        /// Default joystick top
        /// </summary>
        private const int DefaultJoystickVisualTop = 174;

        /// <summary>
        /// Default joystick width
        /// </summary>
        private const int DefaultJoystickVisualWidth = 200;

        /// <summary>
        /// The model state
        /// </summary>
        private GamePadAgentMessage state;

        /// <summary>
        /// Initializes a new instance of the GamePadEmulatorModel class
        /// </summary>
        public GamePadEmulatorModel()
        {
            this.state = new GamePadAgentMessage(
                new GamePadAgentMessage.GamePadAgentButtons(),
                new GamePadAgentMessage.GamePadAgentDPad(),
                new GamePadAgentMessage.GamePadAgentThumbSticks(),
                new GamePadAgentMessage.GamePadAgentTriggers());

            this.JoystickVisualLeft = DefaultJoystickVisualLeft;
            this.JoystickVisualTop = DefaultJoystickVisualTop;
            this.JoystickVisualDiameter = DefaultJoystickVisualWidth;
        }

        /// <summary>
        /// Gets or sets the delegate that controls what is done on a property change.
        /// </summary>
        public Action<GamePadAgentMessage> GamePadEmulatorDelegate
        {
            get;
            set;
        }

        /// <summary>
        /// Gets the left position of the joystick visual
        /// </summary>
        public int JoystickVisualLeft { get; private set; }

        /// <summary>
        /// Gets the top position of the joystick visual
        /// </summary>
        public int JoystickVisualTop { get; private set; }

        /// <summary>
        /// Gets the diameter of the joystick visual
        /// </summary>
        public int JoystickVisualDiameter { get; private set; }

        /// <summary>
        /// Gets or sets the radius of the joystick visual
        /// </summary>
        public int Radius { get; set; }

        /// <summary>
        /// Gets the center X position of the joystick
        /// </summary>        
        public double JoystickVisualCenterX 
        {
            get { return this.JoystickVisualLeft + this.JoystickVisualDiameter / 2; }
        }

        /// <summary>
        /// Gets the center y position of the joystick
        /// </summary>        
        public double JoystickVisualCenterY
        {
            get { return this.JoystickVisualTop + this.JoystickVisualDiameter / 2; }
        }

        /// <summary>
        /// Gets or sets the ending X position of the joystick
        /// </summary>        
        public double JoystickPositionX
        {
            get
            {
                // for the visual, take the joystick value and move and scale to the visual position and size
                return (this.JoystickVisualCenterX + ((this.state.ThumbSticks.Left.X * this.JoystickVisualDiameter) / 2));
            }

            set
            {
                // thumbstick X is a value scaled between -1 and 1
                this.state.ThumbSticks.Left.X = (float)((value) / (this.JoystickVisualDiameter / 2) - 1);
                this.GamePadEmulatorDelegate(this.state);
            }
        }

        /// <summary>
        /// Gets or sets the ending Y position of the joystick
        /// </summary>        
        public double JoystickPositionY
        {
            get
            {
                // for the visual, take the joystick value and move and scale to the visual position and size
                return (this.JoystickVisualCenterY - ((this.state.ThumbSticks.Left.Y * this.JoystickVisualDiameter) / 2));
            }

            set
            {
                // thumbstick Y is a value scaled between -1 and 1
                this.state.ThumbSticks.Left.Y = -(float)((value) / (this.JoystickVisualDiameter / 2) - 1);
                this.GamePadEmulatorDelegate(this.state);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the A button is pressed.
        /// </summary>
        public bool ButtonA
        {
            get
            {
                return this.state.Buttons.A;
            }

            set 
            {
                this.state.Buttons.A = value;
                this.GamePadEmulatorDelegate(this.state);
            }
        }
    }
}
